User's Guide for...

6800 Tiny PILOT

for tiny 6800 computers

Ported from 6502 to 6800 code by Dave Hassler, February, 2024.

Original 6502 version by Nicholas Vrtis for the SYM-1 computer
and presented in MICRO, Sept. 1979 - issue 16, page 41.
Inspired by WADUZITDO (a 256-byte PILOT micro-subset)
by Larry Kheriaty in BYTE, Sept. 1978, pg. 166.

Original 6502 I: L: and P: statement additions (plus KIM-1 I/O)
by Bob Applegate, in MICRO, Aug. 1980, pg. 21.

X: statement, ~ and _ commands, P: rewrite, L: modification, math changes,
and this User's Guide by Dave Hassler, 2024

This User's Guide; the programs Madison's Dilemma, Dicethrow, Division,
Less-Greater, and Tellmedude; and the ported 6800 assembly code of Tiny PILOT,
are copyright (c) 2024 David H. Hassler, and are released under the MIT
licence.  See the full text of the license at the foot of this document.


	*** LOADING and ADAPTING ***

   The Motorola S Record file TINYPILOT6800.S19 should be loaded from
monitor (I use SWTBUG, compatible with MIKBUG), and then executed at $0100.
The interpreter resides from $0000 to $067F, and can run in as little as
2 KB of RAM, although 4 KB is a recommended minimum for creating scripts and
programs of any complexity.
   To adapt for use with other monitors or system configurations, please see
the "EXTERNAL ADDRESS REFERENCES" at the top of the source code (file
TINYPILOT6800.ASM); also edit the routines SETBGN and ZAPRAM.


	*** INTRODUCTION ***

   PILOT stands for Programmed Inquiry, Learning, Or Teaching. PILOT has been
around since 1968, when it was invented by Dr. John Starkweather at the
University of California, San Francisco.  It was designed to be a vehicle
for computer-aided instruction (CAI) in classrooms, and it's wonderful for
that.  It was super-easy for a teacher to use to create an interactive script
that could guide a student through an exercise.  Back then, when a lot
of young teaching students had never used a simple calculator, PILOT was easy
for non-engineers to understand and use with a minimum of instruction.
   The language is dialog driven and well-suited for conversation.  There are
also basic arithmetic and math comparison functions.  The idea for a Tiny
PILOT was conceived by "the dragons" at People's Computer Company (where Tiny
BASIC was also hatched), and a version was eventually created by Nicholas
Vrtis in 1979 for his SYM-1.  His 6502 Tiny PILOT is a small subset of
the PILOT-73 "core" standard, designed to run on the very small "trainer
boards" of the time: no string variables, only addition and subtraction, small
integer number range, etc.  Just as the designers of VTL-2 and Tiny BASIC had
to compromise on features versus size when considering the memory constraints
of the consumer machines of the mid 1970s, Tiny PILOT's Vrtis did the same.
   Still, with a few additions and a little programming, it's quite capable
of doing most things that other high-level languages do.  Best, it's super
simple to learn, and even in 2024, it still allows kids (and kids at heart)
to get hands-on with basic math and computing concepts like variables,
matching/comparison, looping, branching, subroutines, etc.  Tiny PILOT can 
also play games, guide you on adventures, and aid in any academic pursuit.


	*** EDITOR ***

   Command Functions

   ~		Clear both variable and user script RAM areas
   @		Start execution of the PILOT program in memory
   %		Pad to end of line with $80 after overwrite of a line
   ^		Move edit pointer to start of program
   _		Exit Tiny PILOT to SWTBUG monitor, print user script addresses
   \		Display next line of the script/program
  b/s		Backspace to correct typing errors (current line)
  c/r		Carriage return to indicate end of statement line
		(maximum 125 characters per line)

   Command function characters should not be used in a program/script's T:
statements, as the interpreter will try to execute them; nor in R: 
statements.  Also, $ cannot be printed from a script (see T: example, below).


	*** STATEMENTS ***

   A:	ACCEPT/ASK - Input up to 40 characters into ANSWER/CHRS field.

   ?:	Accept NAME - Input up to 40 characters into the NAME and
	ANSWER/CHRS fields simultaneously (see X: statement).

   C:	COMPUTE - Performs arithmetic on variables named A through Z.
	Allowed operations are: +, -, and =; and the range limit is 0-9999.
	C:$=x will place digits of x, in ASCII, in ANSWER field instead of a
	variable (see M: statement).

   E:	EXIT FROM SUBROUTINE - Return-to address of prior USE statement.

   I:x	INPUT - Input a positive number 0-9999 into variable x (A-Z).

   J:x	JUMP - Jump to label n for next line.

   L:x	LEAP TO ML ROUTINE - Calls machine language routine at address
	stored in special ML-calling variable x, which can be A-C.

   M:	MATCH - Compare text or a variable to the last input from terminal
	(A: or ?:) or a variable (C:$=x).  Sets condition flag to Y if equal,
	N if not equal.

   P:x	PSEUDO-RANDOM NUMBER - Puts a pseudo-random number 0-85 into
	variable x, which can be A-Z.

   R:	REMARK - Program remarks, not executed.

   S:	STOP - Stop program and return to editor.  Must be at end of a
	program/script; otherwise, the interpreter crashes.

   T:	TYPE - Display following text on the terminal. $x will display the
	contents of a variable, and $? the current contents of NAME.

   U:x	USE SUBROUTINE - Saves the address of the start of the next line
	and then jumps to label x.

   X:	TRANSFER STRING - Moves the NAME string ('?') to a temporary
	storage location called STRING; moves whatever was in STRING
	into NAME and CHRS (the A: acceptance/“answer” area).


	*** CONDITIONALS, LABELS, VARIABLES ***

   N,Y	NO and YES CONDITIONALS - May precede any statement. E.g.,
	YJ: means jump only if the MATCH flag is Y.
	NT: means print following text only if MATCH flag is N.

   *x	LABEL - May precede any statement or conditional. x = one letter B-Z.  
	Acts as a destination for JUMP or USE.  A and * are reserved for
	system use.

   $x	Variable marker.  In TYPE, causes variable contents to be displayed,
	or prepares them to be matched.  $? indicates the NAME field.
	C:$=x puts a variable into the ANSWER area as a string so it can be
	MATCHed.
	
	Numerical variables are single letters, and are separate from label
	letters and the special machine language call variables.
	The numerical content of a variable may be from 0 to 9999.


	*** EXAMPLES AND NOTES ***

   A:	A:ENVELOPE  (user input)
	This can be compared with the M: statement. Input is stored in the
	ANSWER/CHRS area backwards from $2A to $03.  40 characters, max.

   ?:	?:PENELOPE  (user input)
	A string variable that may be printed with '$?'.  Called NAME, this
	appears to be a holdover from PILOT-73, with educational programs in
	mind.  It is stored in the NAME area from $52 to $2B.  40 characters,
	max.  It is also stored in the ANSWER/CHRS area, simultaneously, so
	you can do a M: immediately to look for a match.  It is, essentially,
	the *one* string variable available, but can only be assigned by user
	input, not from within a program. And, it is also stored backward, as
	with ANSWER. Can (should?) be used with the X: statement.

   C:	C:X=Z+Z+Z+Z	this is X = 4 x Z
	C:X=15-2+6-1	this will leave X with the value 18
	C:X=A		this will leave X with the value of variable A
	It's very similar to BASIC.  Operation is strict left-to-right;
	parentheses not allowed.  $ is a special case:

			  	C:$=X
				M:12
				YJ:Z

	Here, whatever is in X gets put in the ANSWER area as ASCII and is
	matched with the string '12'.  If the ASCII codes that make up X
	match the ASCII for '12', then the Y flag is set and we jump to
	label Z; if not, continue on.
	*** The $=x construct does not work for string variable '?' (it sort
	of works, but you get odd output); for matching the string in ?,
	see the X: statement, below.

   E:	Simply place at the end of a subroutine.  The equivalent of BASIC's
	'RETURN'.
			U:Z
			. . . .
			*ZC:A=B+C
			E:

	From the call with U:, performs the calculation, then returns to the
	line right after the U:Z statement that called the subroutine.

   I:	Form is I:x.  The user is asked for input, which should be a positive
	integer from 0-9999, and that value is assigned to variable x.

   J:x	J:A means jump to the beginning of the script.  J:* means restart
	from the beginning, with variables and flags cleared.  This also
	means letters B through Z are available for labels.

   L:x	The variables referenced are not the numeric variables!  Addresses
	*must* be pre-set in Zero Page locations $A0 to $A5 (two 8-bit hex
	bytes, variables A-C available; see the source code for details)
	before program execution.  To use:
		A) load the desired ML routine into memory, either in the
		    protected RAM from $0680-FF, or after the user's script.
		B) load Tiny PILOT. Prior to execution, set $A0 and $A1
		    to the start of the user ML program.  This equates to
		    ML-jump variable A.
		C) execute Tiny PILOT at $0100.
		D) load user program (via TTY). '@' to run program.
	 	   The called ML routine must end with an RTS
		   to come back to the Tiny PILOT interpreter. E.g.,
		   store locations $A0 and $A1 with #$06 and #$90,
		   and L:A will JSR to $0690.

   M:	Form is M:QUIT,HALT,STO.  MATCH will look at the last input to the
	ANSWER/CHRS area (A:, X:, or ?:) and try to match the first word only
	with the parameters.  If QUIT or HALT or STOP was entered, the flag
	will be set to Y.  However, if STOMACH or QUITE is the first word,
	they will match, also.  MATCH is case-sensitive: 'GREEN' and 'green'
	are completely different.  Further, the following will set the flag
	to N:

		T: WHAT'S YOUR FAVORITE COLOR?
		A:I LIKE BLUE (user)
		M:BLUE
		YT:I AGREE THAT BLUE IS BEST.

	One (albeit complicated) way out of this is to use conditionals and
	add a bunch of possible M: statements:

		T: WHAT'S YOUR FAVORITE COLOR?
		A:I LIKE BLUE (user)
		M:BLUE
		NM:I LIKE BLUE
		YT:I AGREE THAT BLUE IS BEST.

	To match variables, use C:$=x  This will place the ASCII values of
	the variable in the ANSWER/CHRS area. When the program sees M:123,
	it's matching against a literal 3-character ASCII string of '123'.
	You can also use M:$x to match input against the content of variables.

   P:x	Will place a pseudo-random decimal number from 0-85 in variable x.
	Why 0-85?  That's the way the decimal math worked out after using
	the DAA opcode.

   R:	A BASIC 'REM' statement; however, any command or 'reserved' character
	in the statement will get misinterpreted and odd things will result.
	Those characters are: ~ @ $ % ^ * _ \

   S:	The marks the end of the program and an exit back to the 
	editor.  Without it, the program will hang/crash.  When S: is reached
	execution stops and the program pointer is reset to the first line.

   T:	Will print any string <126 characters long, upper and lower case.
	Quotes around the string are not needed. To print out the contents of
	NAME (?:) or a variable, preface it with $.  E.g.,
		T:YOU HAVE $X "MARBLES" LEFT, $?.
	will print out YOU HAVE 12 "MARBLES" LEFT, STAN.  assuming
	X=12 and ?=STAN.

   U:x	Saves a return address to the next line and then jumps
	to the label *x.

   X:	This transfers the contents of the ?: variable (NAME) into the STRING
	area.  Using X: allows for an "additional" string variable that can
	also be tested against anything specified for the M: statement.
	E.g.
		?: DAVE  (user input)
		A:BOB  (user input)
		M:BOB
		YT:IT'S 'BOB'
		X:
		X:
		M:DAVE
		YT:IT'S DAVE
		S:

	Will result in 'IT'S BOB' and 'IT'S DAVE' being printed.  The two X:
	statements place NAME into STRING, then STRING into NAME and
	ANSWER/CHRS, the latter of which M: draws from for tests.
	See the included TELLMEDUDE.PIL program for an example of use.


	*** GAMES AND DEMOS ***

   Included in this package are the following games:
	BLACK MATCH	A NIM-like game	
	DEPTH CHARGE	3-D sub hunt. Runs *very* slowly...
	GUESS85		A number-guessing game
	HURKLE		The old favorite...
	NICOMACHUS	Math puzzle, from 101 BASIC Games, by David Ahl
	ROULETTE	Also from 101...

   The following are scripts for instruction and dialog programs:
	CURRY		A CAI script that addresses inferences
	ELIZA		The classic computer therapist, but in "tiny" form
	MADISON'S
	   DILEMMA	A "Choose Your Own Adventure"-like script
	MONSTER		A very tiny text adventure
	MUSTARD		CAI script that addresses stereotypes
	
   Four demonstration/tutorial programs are included:
	DICETHROW	Simulates two die thrown, reasonable distribution
	DIVISION	Routine for dividing two numbers, with remainder
	LESS-GREATER	Demonstrates lesser- and greater-than comparisons
	TELLMEDUDE	Use of the X: statement to make NAME more versatile

================================================================

	   
	COMMENTS and ERRATA

   Tiny PILOT (like Pittman's Tiny BASIC) can print out lower case letters and
you may respond to an A: or ?: statement in either case.  It will also
differentiate between upper and lower case for a MATCH statement, but all user
script/program statements must be in upper case; the only exceptions are after
T:, R:, or M:.
   E.g.:   T:this is okay.        but not       m:This won't MATCH,no,NO

   There is no "immediate mode" as in most other classic high-level languages.
The editor is very simple.  You cannot insert a line of code in between lines;
you can only replace it with a line of equal or shorter length by typing over.
If the replacement is shorter, end the line with '%' instead of <RETURN>.  
That will pad the remaining space with $80, which will not print and is ignored.
   Backspace (08) works within a line, but frankly, I would not use
the editor for anything other than sketching out ideas or very small programs.
Better to just use Mousepad or Notepad++ or something for script and program
writing, and then upload that via serial terminal.

   You can break Tiny PILOT; there is absolutely no error checking.  Stuff
like not assigning a variable a value and then trying to print it, or 
forgetting to put a ':' after a program statement letter will break it.

   J:* is like typing RUN in BASIC from within a program.  Variables and
several flags get cleared.  Notice that there's no label with it.  It
would be useful for allowing the user (or a different user) to start fresh
automatically without having to restart the program.  Makes sense in a
lower-grades educational/classroom environment.  The one reserved label is
A.  J:A will jump back to the last A: statement.

   There's no cold start with Tiny PILOT -- your program in user RAM is still 
there.	You can even go do other stuff, reload Tiny PILOT, and as long as your 
program from $0700 to its end was undisturbed, it'll run.

   Loading and saving programs is easy.  Today (2024), simply upload an ASCII
text file from your serial terminal emulator running on your modern PC to the
interpreter.  10 ms character and 150 ms line delays seem to work OK.
   ** NOTE: ** It is important to use a *carriage-return-only* line
ending for your Tiny PILOT scripts/programs.  The interpreter uses ASCII $0D
(#13) as the end-of-line character, and does not use a linefeed ($0A/#10) at
all (that wastes a line of program space!).  Most text processors can do this
conversion.
   To load a script from a previously saved Motorola S Record file, simply
load it in with your monitor's load command, either before you load and run
Tiny PILOT, or after -- just exit with the '_' command, load, then (with
SWTBUG) type 'J 0100'.
   To save a script you've written with the internal editor, you can save it:
	1) line by line from the editor.  Open a text capture file on the
serial terminal emulator, type a '^' to go to the beginning of your
program, then start slowly tapping '\' to list it out line by line.  You'll
have to clean it up a bit in post.
	2) use the supplied end-of-script address after exiting Tiny PILOT, 
enter your start and end addresses into your monitor's memory locations for
such things (for SWTBUG, start goes in $A002/3, end in $A004/5; for the
HM-68's modified SWTBUG, that's $7F02/3 and $7F04/5), then punch an .S13 file.
   Of course, you can avoid all of this by writing your programs offline on
Mousepad or Notepad++ or whatever.

   You can append a program/script to another by loading a file after one
already in the user RAM space; just don't use the '^' command to go to the
start of the script.  Issues could also arise if you loaded a longer file, but
then loaded in a shorter file, even after a '^', and end up with an overwrite.
Hence, the '~' command in the editor, so you can avoid the problem...unless,
of course, that's exactly what you want to do.

   I tweaked Bob Applegate's L: statement so Tiny PILOT could be burned into
an EPROM.  Bob's original approach used self-modifying code in a brute-force
way that would have made my then-14-year-old self say "Wow!"  Considering that
Bob was just 17 when he wrote and submitted this to MICRO in 1980 makes it
all that much more fun.  I'm really glad Bob got to see the 6502 code run
again in 2023 on a KIM-1 replica, only months before he passed away.  He said
he'd forgotten all about it, but that it was getting published in MICRO that
convinced his mother to let him leave high school a year early to start
college.

   With the addition of the X: statement, I had to limit Bob's ML calling
routine to just three instances, variables A-C.  That should be plenty.
The 126 bytes between $0682 and $06FF are protected RAM, and will not get
zapped by the '~' clear memory command; if you need more room for a machine
language routine, change the bytes in locations $0489 and $05D0 to $08, and
change location $0657 from $37 to $38.  That moves the start of the user
script/program space to $0800, allowing for 382 bytes of protected RAM.
   Of course, previously saved .S13 files that start at $0700 will not run
properly if loaded.  Just sayin'...  :^)  Finally, Zero Page is pretty locked
up by Tiny PILOT.  Safe locations for use are $CE to $D9, and $F6 to $FF.
   A tricky thing one could do is make an .S13 file of user memory from $0700
to the end of your program, then load and save an .S13 of your ML program
that's *after* the Tiny PILOT script and tack *that* onto the end of your
Tiny PILOT program .S13.  Also, at the very top, add a tiny patch to put the
proper bytes needed for the JSR of the routine in $A0-1 (or wherever).  Then
it's all self-contained and requires no extra work by the end user.

   As for the pseudo-random number routine, it's...well...not very good.  The
best thing I could find that would work with decimal arithmatic is adapted
from Robert Findley's "6800 Software Gourmet Guide & Cookbook" from 1976.
Numbers from 0-85 are generated in a basically random way; I'm sure someone
else with a better math background than me could come up with something
better.

   I think Bob's I: statement for entering numerical variables is genius, and
it did not take much to translate it from 6502 to 6800.  It really amplifies
the utility and	possibilities of Tiny PILOT.  Damn good 6502 code, too.

   As for this program and PILOT, itself, the 6502 version by Nicholas Vrtis
appears to be based upon both WADUZITDO (BYTE, Sept '78) and PILOT-73, which
was the defacto standard on minicomputers in the '70s. In the article from
MICRO #16, Nicholas goes into some detail describing how the program works,
section by section.  It's a good read and very informative.  I recommend it,
in addition to his well-commented source code (which I typed in for 6502 by
hand off a printout ... the complete '80s experience!).  I know I certainly
learned a lot about how to build a high-level language interpreter.

   I only have two real gripes: the M: statement only works on the first word
input and gives up without checking the rest of the string*; and, the only way
to operate on a string, other than printing the	NAME buffer, is a simple M:
via the X: statement.  I have recently learned that most full PILOTs can do
these things, with multiple strings, so all hope is not lost, if someone
wants to find some source code and have at it (a reworking of 6809 Color
Computer Cassette PILOT [RS cat #26-2709], perhaps?).

   No, Tiny PILOT -- or most full-sized PILOTs, for that matter -- is no
mathematical champ.  Tiny PILOT is limited to only addition and subtraction,
positive numbers up to 9,999, and the only comparator is =; although, it's
possible to do multiplication and division with those, plus use a loop to
test for <= and >.  E.g.:

		I:G		a number to test
		C:I=105		limit of loop (could be a variable, too)
		*RC:$=I		move ASCII of I to $
		M:$G		match I ($) against (ASCII of) G
		YJ:V		if = then branch to V label, because G is
		NC:I=I-1	inside the loop.  If <>, dec I
		NM:999		test if I ($) is ASCII '999' (end of loop = 0)
		YJ:W		yes, done, branch to W
		NJ:R		no, loop back
		*VT:$G <= 105	is less than or equal to 105.
		J:Z		go around to Z
		*WT:$G > 105	not in loop, so G is greater than 105.
		*ZS:		end of program

   Not much to work with, yet it's still capable of playing a lot of fun
games and running academic scripts.  But what PILOT excels at is interactive
dialog.  Perhaps, today, it can be a vehicle for a retro adventure game? 
Maybe something like the "Choose Your Own Adventure" books from the 1970s
and '80s?  Who knows?

   However you use Tiny PILOT ... Have Fun!    -- Dave Hassler,  27 Feb 2024

* However, there *is* a patch for 6502 that extends the MATCH statement,
making it more like 'core' PILOT - see MICRO, October 1980.  I found it
messed up my variable/number matching sometimes, so I left it out of the
6800 version of Tiny PILOT.  It shouldn't be too hard to port and add in --
feel free to do so.


	*** LICENSE ***

Portions copyright (c) 2024 David H. Hassler

The MIT License (MIT)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all 
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.

https://mit-license.org/